﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Xml;
using QzgfFrame.Utility.Core.JSON;

namespace QzgfFrame.Utility.Core.Export
{
    public class ExportUtil<T>
    {
        protected log4net.ILog Logger = log4net.LogManager.GetLogger("ExportUtil");

        private IEnumerable<T> _exportlist;
        
        public IEnumerable<T> Exportlist
        {
            get { return _exportlist; }
            set { _exportlist = value; }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="outdata">客户端建立的输出流</param>
        /// <param name="type">导出类型 ，与导出文件的扩展名命名，如excel为xls,xml为xml等</param>
        /// <param name="sheetName"></param>
        /// <param name="fields">跟上面的sql所查询出来的字段里的某些字段对应</param>
        /// <param name="colName">对应的中文名称</param>
        public void Export(out byte[] outdata, String type, String sheetName,String[] fields, String[] colName)
        {
            outdata = new byte[] { };
            //获得执行sql的实现类
            try
            {
                //获得需要导出的记录集
                //ResultSet rs = statementmanager.executeSql(sql, para);
                //根据导出的类型实例化导出类
                ExportFacade exportExc = ExportFactory.GetInstance(type);
                //导出数据
                var exportdt = JSONHelper.ListToDataTable(_exportlist);
                exportExc.Export(out outdata, exportdt, sheetName, fields, colName);

            }
            catch (Exception ex)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Error(ex.ToString());
                }
            }
        }


        /// <summary>
        /// 解析导出文件的配置信息，该信息保存于一个xml文件里，格式如
        /// </summary>
        /// <param name="configfile">文件路径</param>
        /// <returns></returns>
        public Hashtable ExportConfig(String configfile)
        {
            Hashtable configList = new Hashtable();
            try
            {
                //这里采用dom4j的xml解析器
                var context = HttpContext.Current;
                var xml = new XmlDocument();
                xml.Load(context.Server.MapPath(configfile));
                //从配置文件里取得所有需要导出的节点信息
                XmlNodeList nodeList = xml.SelectNodes("/exports/export");
                if (nodeList != null)
                {
                    foreach (XmlNode element in nodeList)
                    {
                        //配置信息对应的类
                        var ei = new ExportInfo();
                        ei.SetSqlId(element.Attributes["sqlId"].Value);
                        ei.SetFileName(element.Attributes["filename"].Value);

                        XmlNodeList cols = element.SelectNodes("column");
                        String[] fields = null;
                        String[] columns = null;
                        if (cols.Count > 0)
                        {
                            fields = new String[cols.Count];
                            columns = new String[cols.Count];
                        }

                        for (int i = 0; i < cols.Count; i++)
                        {
                            XmlNode elCol = cols.Item(i);
                            if (elCol != null)
                            {
                                fields[i] = elCol.Attributes["name"].Value;
                                columns[i] = elCol.InnerText;
                            }
                        }
                        ei.SetFields(fields);
                        ei.SetColumns(columns);
                        XmlNode descNode = element.SelectSingleNode("description");
                        if (descNode != null)
                            ei.SetDescription(descNode.InnerText);
                        if (element.Attributes != null) configList.Add(element.Attributes["id"].Value, ei);
                    }
                }
            }
            catch (Exception ex)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Error(ex);
                }
            }
            return configList;

        }


        protected static void InsertCell<T>(T data, NPOI.SS.UserModel.IRow currentExcelRow, params string[] fields)
        {
            PropertyInfo[] properties = typeof(T).GetProperties(); //获得T类型的所有属性

            for (int cellIndex = 0; cellIndex < fields.Length; cellIndex++)
            {
                var cell = currentExcelRow.CreateCell(cellIndex);

                var pi = properties.First<PropertyInfo>(x => x.Name == fields[cellIndex]);

                var value = pi.GetValue(data, null);  //获得该实例，该属性的值

                #region  类型验证

                if (pi.PropertyType == typeof(int) || pi.PropertyType == typeof(int?)
                       || pi.PropertyType == typeof(Int16) || pi.PropertyType == typeof(Int16?)
                   || pi.PropertyType == typeof(Int32) || pi.PropertyType == typeof(Int32?)
                   || pi.PropertyType == typeof(Int64) || pi.PropertyType == typeof(Int64?)
                   || pi.PropertyType == typeof(long) || pi.PropertyType == typeof(long?)
                   || pi.PropertyType == typeof(decimal) || pi.PropertyType == typeof(decimal?)
                   || pi.PropertyType == typeof(float) || pi.PropertyType == typeof(float?)
                   || pi.PropertyType == typeof(double) || pi.PropertyType == typeof(double?)
                    || pi.PropertyType == typeof(uint) || pi.PropertyType == typeof(uint?)
                   || pi.PropertyType == typeof(UInt16) || pi.PropertyType == typeof(UInt16?)
                  || pi.PropertyType == typeof(UInt32) || pi.PropertyType == typeof(UInt32?)
                  || pi.PropertyType == typeof(UInt64) || pi.PropertyType == typeof(UInt64?)
                   || pi.PropertyType == typeof(ulong) || pi.PropertyType == typeof(ulong?)
                   || pi.PropertyType == typeof(short) || pi.PropertyType == typeof(short?)
                   || pi.PropertyType == typeof(ushort) || pi.PropertyType == typeof(ushort?)
                   )
                {
                    cell.SetCellValue(Convert.ToDouble(value));
                }
                else if (pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(bool?))
                {
                    cell.SetCellValue(Convert.ToBoolean(value));
                }
                else if (pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?))
                {
                    cell.SetCellValue(Convert.ToDateTime(value));
                }
                else
                {
                    cell.SetCellValue(Convert.ToString(value));
                }

                #endregion
            }
        }

    }
}
